/*
	This script file is part of the Sonic 3 A.I.R. script software distribution.
	Copyright (C) 2017-2024 by Eukaryot

	Published under the GNU GPLv3 open source software license, see license.txt
	or https://www.gnu.org/licenses/gpl-3.0.en.html
*/



// Balls inside the machine (only a visual effect)

//# address-hook(0x060ffe) end(0x06100e)
function void fn060ffe()
{
	setupObjectAttributesFull(0x06138c)

	objA0.update_address = 0x061012
	fn061362()
	fn061012()
}


//# address-hook(0x061012) end(0x061018)
function void fn061012()
{
	MoveWithParent()
	DrawObject()
}



//# address-hook(0x06101e) end(0x06102e)
function void fn06101e()
{
	setupObjectAttributesFull(0x0613d4)
	objA0.update_address = 0x061032
	fn061320()
	fn061032()
}


//# address-hook(0x061032) end(0x06103e)
function void fn061032()
{
	--objA0.flags2e
	if (s8[A0 + 0x2e] < 0)
	{
		objA0.update_address = 0x0856d0
	}
	DrawObject()
}



//# address-hook(0x061320) end(0x061340)
function void fn061320()
{
	D0 = 0
	objA0.flags2e = objA0.subtype2c
	A1 = 0x061342 + objA0.subtype2c
	objA0.position.x.u16 += s8[(A1+=1)-1]
	objA0.position.y.u16 += s8[(A1+=1)-1]
}


//# address-hook(0x061362) end(0x061382)
function void fn061362()
{
	D0 = u16(objA0.subtype2c - 6) >> 1
	D0.u8 = u8[0x061388 + D0.u16]
	objA0.animation.sprite = D0.u8
	if (D0.u8 == 0x16)
	{
		// "spawnSimpleChildObjects(0x06144a)" replaced by:
		spawnSimpleChildObjects(0x0610b6, 1)
	}
}



// Check for exiting?

//# address-hook(0x061044) end(0x06104a)
function void fn061044()
{
	objA0.position.y.u16 += 0x02a0
	objA0.update_address = 0x061050
	fn061050()
}


//# address-hook(0x061050) end(0x0610ac)
function void fn061050()
{
	--u16[0xffff2020]
	A1 = 0x0610ae
	fn0858f8()
	if (D0.u16 == 0)
	{
		D0 = (D0 << 16) + (D0 >> 16)
		if (D0.u16 == 0)
			return

		A1 = 0xffffb04a
		UnloadObjectA1()
		return
	}

	global.zone_act = checkpoint.zone_act
	global.zone_act.apparent = checkpoint.zone_act.apparent
	checkpoint.number = checkpoint.number.backup
	global.stage_type = 0
	level.restart.u8 = 1
	checkpoint.rings = ring_counter
	checkpoint.lives_granted = extra_lives_granted
	global.shields_backup_1 = u8[0xffffb000 + 0x2b] & char.bonus.ALL_SHIELDS
}



// And the main gum machine...?

//# address-hook(0x0610b6) end(0x0610c0)
function void fn0610b6()
{
	setupObjectAttributesFull(0x0613ec)
	objA0.update_address = 0x0610c6
	fn0610c6()
}


//# address-hook(0x0610c6) end(0x0610da)
function void fn0610c6()
{
	u8[0xffffef3a] = 0xff
	A1 = 0xffff0000 + u16[A0 + 0x46]
	objA0.position.x.u16 = objA1.position.x.u16
	objA0.position.y.u16 = objA1.position.y.u16
	DrawObject()
}



// Falling bonus bubble

//# address-hook(0x060eba) end(0x060eca)
function void fn060eba()
{
	setupObjectAttributesFull(0x0613e0)
#if STANDALONE
	objA0.box_size.x = 0x10		// Larger visual bounding box to prevent early clipping
	objA0.box_size.y = 0x10
#endif

	objA0.update_address = 0x060ece
	fn0612a8()
	fn060ece()
}


//# address-hook(0x060ece) end(0x060f28)
function void fn060ece()
{
	objA0.velocity.y = min(objA0.velocity.y + 0x10, 0x0200)

	UpdateMovementStraightSimple()
	A1 = 0xffff0000 + u16[A0 + 0x46]
	D0.u16 = objA1.position.y.u16
	if (D0.u16 > objA0.position.y.u16)
	{
		objA0.position.y.u16 = D0.u16
	}
	else
	{
		D0.u16 += 0x10
		if (D0.u16 <= objA0.position.y.u16)
		{
			fn0610e0()
			if (!_equal())
			{
				UnloadObject()
				return
			}
		}
	}

	D0.u16 = camera.position.y.u16 + 0x0240
	if (D0.u16 >= objA0.position.y.u16)
	{
		Object.AnimationProgressByLocalA1()
		DrawObject()
	}
	else
	{
		UnloadObject()
	}
}


//# address-hook(0x0610e0) end(0x0610ee)
function void fn0610e0()
{
	A1 = 0x0610f0
	fn0858f8()
	_setZeroFlagByValue(D0)
	if (D0 != 0)
	{
		fn0610f8()
	}
}


//# address-hook(0x0612a8) end(0x0612de)
function void fn0612a8()
{
	u8 rnd = getRandomNumber() & 0x0f

	// This code makes sure you can't get more than one 1-up per run of the Gumball Machine stage
	if (rnd == 0)
	{
		A1 = 0xffff0000 + u16[A0 + 0x46]
		if (u8[A1 + 0x38] & 0x80)
		{
			// We had one already, now switch to a black bubble instead
			rnd = 3
		}
		else
		{
			// Allow 1-up
			u8[A1 + 0x38] |= 0x80
		}
	}

	// Set bonus bubble content and sprite based on the previous chosen random value
	u8 bubbleType = u8[0x0612e0 + rnd]

#if STANDALONE
	// Don't spawn 1-ups with the infinite lives setting on, instead replace with a ring bubble
	if (bubbleType == 0x00 && Game.getSetting(SETTING_INFINITE_LIVES))
		bubbleType = 0x02
#endif

	// Bubble types:
	//  0x00 = 1-up bubble
	//  0x01 = Rep bubble
	//  0x02 = Ring bubble
	//  0x03 = Empty bubble
	//  0x04 = Bouncy black bubble
	//  0x05 = Fire shield
	//  0x06 = Bubble shield
	//  0x07 = Lightning shield
	//  0x08 = Unused golden "Super bubble"
	objA0.subtype2c = bubbleType
	if (bubbleType == 0x04)
	{
		// Bouncy black bubble hitbox
		objA0.collision_attributes = (collision.flag.SPECIAL | collision.size.8x8_2)
	}
	u32[A0 + 0x30] = u32[0x0612f0 + bubbleType * 4]
}
